﻿/*
// Exepack.NET compressor
// http://www.codeplex.com/exepack
//
// Options treeview
// Written by Y [24-01-10]
// Copyright (c) 2008-2010 Alexey Yakovlev
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Exepack
{
	/// <summary>
	/// Links CompressionOptions with a TreeView
	/// </summary>
	class CompressionOptionsView
	{
		public CompressionOptionsView(TreeView treeView)
		{
			if (treeView == null)
				throw new ArgumentNullException("treeView");

			TreeView = treeView;
			CompressionOptions = null;
			AssemblyNodes = new Dictionary<TreeNode,AssemblyInformation>();
		}

		/// <summary>
		/// TreeNode -> AssemblyInformation
		/// </summary>
		private Dictionary<TreeNode, AssemblyInformation> AssemblyNodes { get; set; }

		/// <summary>
		/// Returns object (either CompressionOptions or AssemblyInformation) associated with the selected tree node
		/// </summary>
		public object this[TreeNode node]
		{
			get
			{
				if (node.Parent == null)
					return CompressionOptions;

				return AssemblyNodes[node];
			}
		}

		/// <summary>
		/// Compression options for an executable
		/// </summary>
		public CompressionOptions CompressionOptions { get; private set; }

		/// <summary>
		/// TreeView which displays compression options
		/// </summary>
		public TreeView TreeView { get; private set; }

		/// <summary>
		/// Clears compression options
		/// </summary>
		public void Clear()
		{
			CompressionOptions = null;
			SynchronizeTreeView();
		}

		/// <summary>
		/// Adds single assembly
		/// </summary>
		public void Add(string fileName)
		{
			if (CompressionOptions == null)
				CompressionOptions = CompressionOptions.Create(fileName);
			else
				CompressionOptions.Add(fileName);

			SynchronizeTreeView();
		}

		/// <summary>
		/// Adds assembly and all its references recursively
		/// </summary>
		public void AddRecursive(string fileName)
		{
			if (CompressionOptions == null)
				CompressionOptions = CompressionOptions.Create(fileName);
			else
				CompressionOptions.AddRecursive(fileName);

			SynchronizeTreeView();
		}

		/// <summary>
		/// Synchronizes tree view with current CompressionOptions
		/// </summary>
		private void SynchronizeTreeView()
		{
			if (CompressionOptions == null)
			{
				TreeView.Nodes.Clear();
				AssemblyNodes.Clear();
				return;
			}

			// disable redrawing tree view
			TreeView.BeginUpdate();
			try
			{
				// root node is CompressionOptions
				TreeNode rootNode = null;
				if (TreeView.Nodes.Count > 0)
					rootNode = TreeView.Nodes[0];
				else
				{
					rootNode = new TreeNode(CompressionOptions.MainAssembly.FileName)
					{
						ImageIndex = (int)AssemblyTypes.Executable
					};

					TreeView.Nodes.Add(rootNode);
				}

				// delete subnodes
				AssemblyNodes.Clear();
				rootNode.Nodes.Clear();

				// re-create subnodes ordered alphabetically
				var asms = CompressionOptions.AdditionalAssemblies.OrderBy(v => v.FullName);
				foreach (var asm in asms)
				{
					var node = new TreeNode(asm.FileName)
					{
						ImageIndex = (int)AssemblyTypes.Library
					};

					if (asm.IsSystemAssembly || !asm.IsILOnly)
					{
						node.ForeColor = SystemColors.GrayText;
						node.ImageIndex = (int)AssemblyTypes.Unused;
					}

					AssemblyNodes[node] = asm;
					rootNode.Nodes.Add(node);
				}

				rootNode.Expand();
			}
			finally
			{
				// enable redrawing
				TreeView.EndUpdate();
			}
		}
	}
}
